import { useState } from 'react';
import createEngine, { 
    DefaultLinkModel, 
    DefaultNodeModel,
    DiagramModel,
} from '@projectstorm/react-diagrams';
import {
    CanvasWidget
} from '@projectstorm/react-canvas-core';
import { DatabaseNodeFactory, DatabaseNodeModel } from './DatabaseNode';

import './App.css';

const COLOR_OUT = 'rgb(0, 192, 255)';
const COLOR_IN = 'rgb(192, 255, 0)';

const TYPE_OUT = 'out';
const TYPE_IN = 'in';

const engine = createEngine();
const model = new DiagramModel();
engine.setModel(model);

engine.getNodeFactories().registerFactory(new DatabaseNodeFactory());

const node1 = new DefaultNodeModel('Node 1', COLOR_OUT);
node1.setPosition(100, 100);
const port1 = node1.addOutPort('Out');

const node2 = new DefaultNodeModel('Node 2', COLOR_IN);
const port2 = node2.addInPort('In');
node2.setPosition(400, 100);

const node3 = new DatabaseNodeModel();
node3.setPosition(250, 250);

const link = port1.link<DefaultLinkModel>(port2);
link.addLabel('Label');

model.addAll(node1, node2, link, node3);

/*
    !------------- SERIALIZING ------------------
    const str = JSON.stringify(model.serialize());

    !------------- DESERIALIZING ----------------
    const model2 = new DiagramModel();
    model2.deserializeModel(JSON.parse(str), engine);
    engine.setModel(model2);
*/

export function App() {
    // Только чтобы был рендер
    const [nodesCount, setNodesCount] = useState(2);
    const [serializeText, setSerializeText] = useState('Пусто');

    return (
        <div className='app'>
            <div className='header'>
                <div
                    draggable
                    onDragStart={(event) => {
                        event.dataTransfer.setData('storm-diagram-node', JSON.stringify({ type: TYPE_IN }));
                    }}
                    className="variant-node"
                    style={{ borderColor: COLOR_IN }}
                >
                    In Node
                </div>
                <div
                    draggable
                    onDragStart={(event) => {
                        event.dataTransfer.setData('storm-diagram-node', JSON.stringify({ type: TYPE_OUT }));
                    }}
                    className="variant-node"
                    style={{ borderColor: COLOR_OUT }}
                >
                    Out Node
                </div>
                <button
                    className="button"
                    onClick={() => {
                        setSerializeText(JSON.stringify(model.serialize(), null, 2));
					}}
                >
                    Serialize Graph
                </button>
            </div>
            <div className="content">
                <div
                    className="drop-place"
                    onDrop={(event) => {
                        const data = JSON.parse(event.dataTransfer.getData('storm-diagram-node'));
                        // const nodesCount = engine.getModel().getNodes().length;

                        let node: DefaultNodeModel | null = null;
                        if (data.type === TYPE_IN) {
                            node = new DefaultNodeModel('Node ' + (nodesCount + 1), COLOR_IN);
                            node.addInPort('In');
                        } else {
                            node = new DefaultNodeModel('Node ' + (nodesCount + 1), COLOR_OUT);
                            node.addOutPort('Out');
                        }

                        const point = engine.getRelativeMousePoint(event);
                        node.setPosition(point);
                        engine.getModel().addNode(node);
                        
                        // this.forceUpdate();
                        setNodesCount((prev) => prev + 1);
                    }}
                    onDragOver={(event) => {
                        event.preventDefault();
                    }}
                >
                    <CanvasWidget className="canvas" engine={engine} />
                </div>
                <div className="serialize-place">
                    <pre>
                        {serializeText}
                    </pre>
                </div>
            </div>
        </div>
    );
}